package com.example.blog.module.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.blog.module.entity.ArticleLike;
import com.example.blog.module.entity.Follow;
import com.example.blog.module.entity.Message;
import com.example.blog.module.entity.SysUser;
import com.example.blog.module.entity.VO.UserVo;
import com.example.blog.module.mapper.FollowMapper;
import com.example.blog.module.mapper.MessageMapper;
import com.example.blog.module.service.FollowService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.blog.module.service.SysUserService;
import com.example.blog.module.utils.BaseContent;
import com.example.blog.module.utils.RedisKeyUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zjx
 * @since 2023-04-06
 */
@Service
@RequiredArgsConstructor
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements FollowService {

    private final RedisTemplate redisTemplate;

    private final SysUserService sysUserService;

    private final FollowMapper followMapper;

    private final MessageMapper messageMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean follow(Long followId) {
        Long userId = BaseContent.get().getId();
        String key = RedisKeyUtil.getEntityFollowKey("user",userId);
        Boolean isExits = redisTemplate.hasKey(key);
        Boolean isFollow;
        if (isExits){
            isFollow = redisTemplate.opsForSet().isMember(key,followId);
        }
        else {
            LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Follow::getUserId,userId);

            //将
            List<Long> followIds = followMapper.selectList(wrapper).stream().map(Follow::getUserId).collect(Collectors.toList());
            //判断 userid 是否在 fansId 里
            isFollow = followIds.stream().anyMatch(followId::equals);

            for (Long id:followIds) {
                redisTemplate.opsForSet().add(key,id);
            }
        }
        if (isFollow){
            LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Follow::getUserId,userId);
            wrapper.eq(Follow::getFollowUserId,followId);
            followMapper.delete(wrapper);

            //取关删除相应的私信
            String conservationId = followId<userId ? followId+"_"+userId :userId+"_"+followId;
            LambdaQueryWrapper<Message> wrapper1 =new LambdaQueryWrapper<>();
            wrapper1.eq(Message::getConversationId,conservationId);
            messageMapper.delete(wrapper1);

            redisTemplate.opsForSet().remove(key,followId);
        }else {
            Follow follow = new Follow();
            follow.setUserId(userId);
            follow.setFollowUserId(followId);
            follow.setCreateTime(new Date());

            //关注发送相应私信
            String conservationId = followId<userId ? followId+"_"+userId :userId+"_"+followId;
            Message message = new Message();
            message.setStatus(0L);
            message.setContent("你好，感谢关注");
            message.setFromId(followId);
            message.setToId(userId);
            message.setCreateTime(new Date());
            message.setConversationId(conservationId);
            messageMapper.insert(message);

            followMapper.insert(follow);
            redisTemplate.opsForSet().add(key,followId);
        }

        return !isFollow;
    }

    @Override
    public List<UserVo> queryFollow() {
        Long userId = BaseContent.get().getId();
        String key = RedisKeyUtil.getEntityFollowKey("user",userId);
        Boolean isExits = redisTemplate.hasKey(key);
        if (!isExits){
            LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Follow::getUserId, userId);
            List<Long> followIds = followMapper.selectList(wrapper).stream().map(Follow::getFollowUserId).collect(Collectors.toList());
            for (Long id:followIds) {
                redisTemplate.opsForSet().add(key,id);
            }
        }
        return idsToVo(redisTemplate.opsForSet().members(key));
    }

    @Override
    public List<UserVo> queryFans() {
        Long userId = BaseContent.get().getId();
        String key = RedisKeyUtil.getEntityFansKey("user",userId);
        Boolean isExits = redisTemplate.hasKey(key);
        if (!isExits){
            LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Follow::getFollowUserId, userId);
            List<Long> followIds = followMapper.selectList(wrapper).stream().map(Follow::getUserId).collect(Collectors.toList());
            for (Long id:followIds) {
                redisTemplate.opsForSet().add(key,id);
            }
        }
        return idsToVo(redisTemplate.opsForSet().members(key));
    }

    @Override
    public Integer followStatus(Long followId){
        Long userid = BaseContent.get().getId();
        String entityLikeKey = RedisKeyUtil.getEntityFollowKey("user", userid);
        Boolean isExits = redisTemplate.hasKey(entityLikeKey);
        if (!isExits){
            LambdaQueryWrapper<Follow> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Follow::getUserId, userid);
            List<Long> followIds = followMapper.selectList(wrapper).stream().map(Follow::getFollowUserId).collect(Collectors.toList());
            for (Long id:followIds) {
                redisTemplate.opsForSet().add(entityLikeKey,id);
            }
        }
        return redisTemplate.opsForSet().isMember(entityLikeKey,followId) ? 1 : 0;
    }

    public List<UserVo> idsToVo(Set<Long> ids){
        List<UserVo> userVos = new ArrayList<>();
        for (Long id: ids
             ) {
            SysUser sysUser = sysUserService.findUserById(id);
            UserVo userVo = new UserVo();
            userVo.setId(sysUser.getId());
            userVo.setNickname(sysUser.getNickname());
            userVo.setAvatar(sysUser.getAvatar());
            userVo.setIsFollow(1);
            userVos.add(userVo);
        }
        return userVos;
    }
}
